using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using AutumnEngine.Modules;
using System.Diagnostics;
using AutumnEngine;

namespace AutumnEngine.Modules
{
    /// <summary>
    /// Handles debug drawing.
    /// </summary>
    public class DebugModule : Module
    {
        internal SpriteFont Font
        {
            get;
            set;
        }

        Stopwatch timer;
        Stopwatch betweenDraws;
        Stopwatch fps;
        int fr = 0;
        /// <summary>
        /// Gets or sets the debug text. Each KeyValuePair is drawn, in the format of Key : Value.
        /// Values are not automatically updated.
        /// </summary>
        /// <value>The debug text.</value>
        public Dictionary<string, object> DebugText
        {
            get;
            set;
        }

        int frame = 0;

        /// <summary>
        /// Creates this instance.
        /// </summary>
        public override void Create()
        {
            DebugText = new Dictionary<string, object>();
            DebugText.Add("Engine Version", Engine.Modules.Settings.EngineVersion);
            DebugText.Add("Frames", 0);
            DebugText.Add("Last Log Message", "");
#if ZUNE
            Font = Engine.Modules.EmbeddedContentManager.Load<SpriteFont>("DebugFontZune");
#endif
#if XBOX
            Font = Engine.Modules.EmbeddedContentManager.Load<SpriteFont>("DebugFont360");
#endif
#if WINDOWS
            Font = Engine.Modules.EmbeddedContentManager.Load<SpriteFont>("DebugFontWin");
#endif
            DebugText.Add("Frame Draw Time","1");
            DebugText.Add("Frame Draw Delay", "14");

            DebugText.Add("Frames Per Second", "0");
            timer = new Stopwatch();
            betweenDraws = new Stopwatch();
            fps = new Stopwatch();
            fps.Start();
            base.Create();
        }

        public float FrameDrawTime
        {
            get { return ((float)(timer.ElapsedTicks / 10000f)); }
        }

        public float FrameDrawDelay
        {
            get { return ((float)(betweenDraws.ElapsedTicks / 10000f)); }
        }

        public float FramesPerSecond
        {
            get;
            private set;
        }

        const int milBetweenFpsUpdate = 1000;

        /// <summary>
        /// Draws this instance.
        /// </summary>
        public override void NoneTranslatedDraw()
        {
            frame++;
            fr++;
           
            string tota = "";
            foreach (KeyValuePair<string, object> k in DebugText)
            {
                string form = String.Format("{0} : {1}", k.Key, k.Value);
                tota += form;
                tota += "\n";
                
            }
            Engine.SpriteBatch.DrawString(Font, tota, new Vector2(5,5), Engine.Modules.Settings.DebugColor);
            
            base.NoneTranslatedDraw();
        }

        internal void BeginDraw()
        {
            timer.Stop();
            timer.Reset();
            timer.Start();
            betweenDraws.Stop();
        }

        internal void EndDraw()
        {
            timer.Stop();
            betweenDraws.Reset();
            betweenDraws.Start();
        }

        public override void Update()
        {
            DebugText["Frame Draw Time"] = this.FrameDrawTime.ToString() + " Ms";
            DebugText["Frames"] = frame;
            DebugText["Frame Draw Delay"] = this.FrameDrawDelay.ToString() + " Ms";
            //If in update, less resource intensive though less precise (Operates in 16ms loops)
            //Draw runs as fast as possible, though shouldn't be used for anything other than drawing.
            if (fps.ElapsedMilliseconds >= milBetweenFpsUpdate)
            {
                FramesPerSecond = fr * (1000 / milBetweenFpsUpdate);
                fr = 0;
                fps.Reset();
                fps.Start();
            }
            
            DebugText["Frames Per Second"] = this.FramesPerSecond.ToString();
            base.Update();
        }
    }
}